using System.Collections.Generic;
using System.Windows.Forms;
using System;

namespace MagicAttributeTest
{
  // Event delegate used for GUI (Permanent) Interactions
  public delegate void GUIPermanentEventHandler(Permanent permanent);
  public delegate void GUIAbilityEventHandler(Permanent permanent, Ability ability);
  public delegate void GUIManaEventHandler(char Single);
  public delegate void GUIEventHandler();

  public class GUIAction
  {
    public bool m_bInitialized = false;
    public bool IsInitialized() { return m_bInitialized; }
    public void SetInitialized() { m_bInitialized = true; }
    // Is Called when a GUI-Item on top of the stack is popped and this item becomes the top item
    public virtual void PopOnTop(GUIAction LastOnTopGUI) { }
    // Is Called when this GUI-Item is pushed on top of the stack
    public virtual void PushOnTop() { SetInitialized(); }
    public virtual bool ClickManaPool(char mana) { return false; } // true if Mana was consumed, false else
    public virtual void ClickPermanentInPlay(Permanent permanent) { }
    public virtual void ClickAbility(Permanent permanent, Ability ability) { }
    public virtual void ClickHandCard(Permanent permanent) { }
  }

  public class PlaySpellGUIAction : GUIAction
  {
    public List<MagicCosts> Costs;
    public MagicPlayer Player;
    public Permanent CardToBePlayed;

    public override void PushOnTop()
    {
      SetInitialized();
      if (CardToBePlayed.HasType(Type.Land))
      {
        PlayAction playAction = new PlayAction();
        playAction.CardPlayed = CardToBePlayed;
        playAction.Player = Player;
        playAction.Costs = Costs;
        Global.InitiateGameAction(playAction);
        Global.GuiState.PopStack();
      }
      else
      {
        PayManaCostGUIAction PayManaGUI = new PayManaCostGUIAction();
        PayManaGUI.Costs = (ManaCosts)Costs[0]; //Cost HACK RSK
        Global.GuiState.PushStack(PayManaGUI);
      }
    }
    public override void PopOnTop(GUIAction LastOnTopGUI)
    {
      PayManaCostGUIAction PayManaGUI = (PayManaCostGUIAction)LastOnTopGUI;
    }
  }

  public class ActivateAbilityGUIAction : GUIAction
  {
    public List<MagicCosts> ActivationCosts;
    public MagicPlayer Player;
    public Permanent AbilitySource;
    public ActivatedAbility AbilityToBeActivated;

    public override void PushOnTop()
    {
      SetInitialized();

      PayManaCostGUIAction PayManaGUI = new PayManaCostGUIAction();
      PayManaGUI.Costs = (ManaCosts)ActivationCosts[0]; //Cost HACK RSK
      Global.GuiState.PushStack(PayManaGUI);
    }

    public override void PopOnTop(GUIAction LastOnTopGUI)
    {
      PayManaCostGUIAction PayManaGUI = (PayManaCostGUIAction)LastOnTopGUI;

      ActivateAbilityAction action = new ActivateAbilityAction();
      action.AbilitySource = AbilitySource;
      action.Player = Player;
      action.ActivationCosts = ActivationCosts;
      action.Ability = AbilityToBeActivated;
      Global.InitiateGameAction(action);
      Global.GuiState.PopStack();
    }
  }

  public class NormalGUIAction : GUIAction
  {
    public override void ClickPermanentInPlay(Permanent permanent)
    {
      MessageBox.Show(this.ToString() + Environment.NewLine +
                      "ClickPermanentInPlay: " + permanent.ToString());
    }
    public override void ClickHandCard(Permanent permanent)
    {
      MessageBox.Show(this.ToString() + Environment.NewLine +
                      "ClickHandCard: " + permanent.ToString());
      //... Play Card (No Check Done Yet or Whatsoever)
      PlaySpellGUIAction GUIPlaySpell = new PlaySpellGUIAction();
      GUIPlaySpell.CardToBePlayed = permanent;
      GUIPlaySpell.Player = permanent.Owner;
      GUIPlaySpell.Costs = permanent.Original.CastingCosts.GetCopyCosts();

      Global.GuiState.PushStack(GUIPlaySpell);
    }
    public override void ClickAbility(Permanent permanent, Ability ability) 
    {
      //... Play Card (No Check Done Yet or Whatsoever)
      ActivatedAbility activatedAbility = ability as ActivatedAbility;
      if (activatedAbility != null)
      {
        ActivateAbilityGUIAction GUIActivateAbility = new ActivateAbilityGUIAction();
        GUIActivateAbility.AbilitySource = permanent;
        GUIActivateAbility.Player = permanent.Owner;
        GUIActivateAbility.ActivationCosts = permanent.Original.CastingCosts.GetCopyCosts();
        GUIActivateAbility.AbilityToBeActivated = activatedAbility;
        Global.GuiState.PushStack(GUIActivateAbility);
      }
    }
  }

  public class PayManaCostGUIAction : GUIAction
  {
    public ManaCosts Costs;
    public override void ClickPermanentInPlay(Permanent permanent)
    {
    }
    public override bool ClickManaPool(char SingleMana)
    {
      MessageBox.Show(this.ToString() + Environment.NewLine +
                      "ClickManaPool: " + SingleMana.ToString());
      if (!Costs.Pay(SingleMana))
        return false;
      if (Costs.IsAllPaid())
        Global.GuiState.PopStack();
      return true;
    }
  }

  public class GUIState
  {
    public Stack<GUIAction> m_Stack = new Stack<GUIAction>();

    public void PushStack(GUIAction obj)
    {
      m_Stack.Push(obj);
      obj.PushOnTop();
    }
    public void PopStack()
    {
      GUIAction FinishedGUIAction = m_Stack.Pop();
      m_Stack.Peek().PopOnTop(FinishedGUIAction);
    }
    public void ClickPermanentInPlay(Permanent permanent)
    {
      m_Stack.Peek().ClickPermanentInPlay(permanent);
    }
    public void ClickHandCard(Permanent permanent)
    {
      m_Stack.Peek().ClickHandCard(permanent);
    }
    public void ClickManaPool(char SingleMana)
    {
      bool bManaUsed = m_Stack.Peek().ClickManaPool(SingleMana);

      if (bManaUsed)
      {
        if (!Global.GuiPlayer.ManaPool.Subtract(SingleMana))
          throw new Exception("Cannot Pay Mana Costs!!!");
      }
    }
    public void ClickAbility(Permanent permanent, Ability ability)
    {
      m_Stack.Peek().ClickAbility(permanent, ability);
    }
  }
}